package mule.presenter;

import java.util.Random;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.stage.Stage;
import javafx.util.Duration;
import mule.model.GameModel;
import mule.model.StoreModel;
import mule.model.enums.MuleOutfit;
import mule.view.GameView;

/**
 * This presenter is the most important, by far. It loads the main game view
 * and controls all of the player interactions while they are playing.
 *
 * @author stephen
 */
public class GamePresenter implements Presenter{
    protected final GameModel model;
    protected final GameView view;
    protected final StoreModel store;
    protected final Stage stage;

    /**
     * Constructs a new presenter with a reference to the stage, the model,
     * the store, and the view that it is presenting.
     * 
     * @param stage The stage to present
     */
    public GamePresenter( Stage stage )
    {
        this.stage = stage;
        this.model = GameModel.getInstance();
        this.store = StoreModel.getInstance();
        this.view = new GameView( model.tileMapProperty(), stage );
    }

    /* COMMENT THESE OUT BEFORE THE FINAL SUBMISSION */
    // <editor-fold defaultstate="collapsed" desc="Methods for Testing">
    protected GameModel getModelForTesting()
    {
        return model;
    }
    
    protected GameView getViewForTesting()
    {
        return view;
    }
    
    protected StoreModel getStoreForTesting()
    {
        return store;
    }
    //</editor-fold>
    
    @Override
    public void present() 
    {
        addBindings();
        stage.setScene( view.getScreen() );
        addListeners();
        stage.show();
    }

    @Override
    public void addListeners() 
    {
        view.addTimerFinishedListener( new EventHandler<ActionEvent>() 
        {
            @Override
            public void handle( ActionEvent event ) 
            {
                if( model.getNextPlayer() == model.players.get( 0 ) )
                {
                    model.setGameStage( model.getNextGameStage() );
                }

                model.setTurn( model.getNextPlayer() );
                view.killPopups();
            } 
        } );

        view.addBuyMuleListener( new EventHandler<ActionEvent>()
        {
            @Override
            public void handle( ActionEvent event )
            {
                if( model.getTurn().getMule() == null )
                {
                    System.out.print(model.getTurn().getName() + "\n");
                    System.out.print(model.getTurn().getMoney() + "->");
                    model.getTurn().addMule();
                    model.getTurn().setMoney( model.getTurn().getMoney() - 100 );
                    store.setMuleCount(store.getMuleCount() - 1);
                    view.killPopups();
                    System.out.print(model.getTurn().getMoney() + "\n");
                }
            }
        } );

        view.addBuyFoodFactoryListener( new EventHandler<ActionEvent>()
        {
            @Override
            public void handle( ActionEvent event )
            {
                if( model.getTurn().getMule() != null && model.getTurn().getMule().getOutfit() != null )
                {
                    model.getTurn().getMule().setOutfit( MuleOutfit.FOOD_FACTORY );
                    model.getTurn().setMoney( model.getTurn().getMoney() - 25 );
                    view.killPopups();
                }
            }
        } );

        view.addBuyEnergyFactoryListener( new EventHandler<ActionEvent>()
        {
            @Override
            public void handle( ActionEvent event )
            {
                if( model.getTurn().getMule() != null && model.getTurn().getMule().getOutfit() != null )
                {
                    model.getTurn().getMule().setOutfit( MuleOutfit.ENERGY_FACTORY );
                    model.getTurn().setMoney( model.getTurn().getMoney() - 50 );
                    view.killPopups();
                }
            }
        } );

        view.addBuyOreFactoryListener( new EventHandler<ActionEvent>()
        {
            @Override
            public void handle( ActionEvent event )
            {
                if( model.getTurn().getMule() != null && model.getTurn().getMule().getOutfit() != null )
                {
                    model.getTurn().getMule().setOutfit( MuleOutfit.ORE_FACTORY );
                    model.getTurn().setMoney( model.getTurn().getMoney() - 75 );
                    view.killPopups();
                }
            }
        });

        view.addGambleListener( new EventHandler<ActionEvent>()
        {
            @Override
            public void handle( ActionEvent event )
            {
                int timeLeft = view.timeSeconds.get() / 100;
                int roundBonus = model.gambleValues.get( model.getRound() );
                Random rand = new Random();
                int timeBonus = rand.nextInt( timeLeft );
                int totalBonus = timeBonus + roundBonus;

                model.getTurn().setMoney( model.getTurn().getMoney() + totalBonus );
                if( model.getNextPlayer() == model.players.get( 0 ) )
                {
                    model.setGameStage( model.getNextGameStage() );
                }

                model.setTurn( model.getNextPlayer() );
                view.killPopups();
            }
        } );

        view.addBuyFoodListener( new EventHandler<ActionEvent>()
        {
            @Override
            public void handle( ActionEvent event )
            {
                if( model.getTurn().getMoney() > 30 && store.getFood() >= 1 )
                {
                    model.getTurn().setFood( model.getTurn().getFood() + 1 );
                    model.getTurn().setMoney( model.getTurn().getMoney() - 30 );
                    store.setFood( store.getFood() - 1 );
                }
            }
        });

        view.addBuyEnergyListener( new EventHandler<ActionEvent>()
        {
            @Override
            public void handle( ActionEvent event )
            {
                if( model.getTurn().getMoney() > 25 && store.getEnergy() >= 1 )
                {
                    model.getTurn().setEnergy( model.getTurn().getEnergy() + 1 );
                    model.getTurn().setMoney( model.getTurn().getMoney() - 25 );
                    store.setEnergy( store.getEnergy() - 1 );
                }
            }
        });
        
        view.addBuyOreListener( new EventHandler<ActionEvent>()
        {
            @Override
            public void handle( ActionEvent event )
            {
                if( model.getTurn().getMoney() > 50 && store.getOre() >= 1 )
                {
                    model.getTurn().setOre( model.getTurn().getOre() + 1 );
                    model.getTurn().setMoney( model.getTurn().getMoney() - 50 );
                    store.setOre( store.getOre() - 1 );
                }
            }
        });

        view.addSellFoodListener( new EventHandler<ActionEvent>()
        {
            @Override
            public void handle( ActionEvent event )
            {
                if( model.getTurn().getFood() >= 1 )
                {
                    model.getTurn().setFood( model.getTurn().getFood() - 1 );
                    model.getTurn().setMoney( model.getTurn().getMoney() + 30 );
                    store.setFood( store.getFood() + 1 );
                }
            }
        } );

        view.addSellEnergyListener( new EventHandler<ActionEvent>()
        {
            @Override
            public void handle( ActionEvent event )
            {
                if( model.getTurn().getEnergy() >= 1 )
                {
                    model.getTurn().setEnergy( model.getTurn().getEnergy() - 1 );
                    model.getTurn().setMoney( model.getTurn().getMoney() + 25 );
                    store.setEnergy( store.getEnergy() + 1 );
                }
            }
        });
        
        view.addSellOreListener( new EventHandler<ActionEvent>()
        {
            @Override
            public void handle( ActionEvent event )
            {
                if( model.getTurn().getOre() >= 1 )
                {
                    model.getTurn().setOre( model.getTurn().getOre() - 1 );
                    model.getTurn().setMoney( model.getTurn().getMoney() + 50 );
                    store.setOre( store.getOre() + 1 );
                }
            }
        });
        
        view.addPassTurnListener( new EventHandler<ActionEvent>()
        {
            @Override
            public void handle( ActionEvent event )
            {
                view.timeline.playFrom( Duration.seconds( 30 ) );
            }
        });
    }

    /**
     * Binds many of the fields from the model to the view so that they can
     * be constantly updated.
     */
    public void addBindings()
    {
        view.bindInformationText( model.informationTextProperty() );
        view.bindGameStage( model.gameStageProperty() );
        view.bindStoreEnergyCount( store.energyProperty() );
        view.bindStoreFoodCount( store.foodProperty() );
        view.bindStoreMuleCount( store.muleCountProperty() );
        view.bindStoreOreCount( store.oreProperty() );
        view.bindCurrentPlayer( model.turnProperty() );
    }

}
